﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.ComponentModel;
using System.Data;

namespace SocketLibrary
{
    public class TcpSvr
    {
        /// <summary>
        /// 连接上得通讯
        /// </summary>
        private Socket m_socket;
        /// <summary>
        /// socket的网络通讯流
        /// </summary>
        private NetworkStream m_net_work_stream;
        /// <summary>
        /// 接受数据的工作线程
        /// </summary>
        private BackgroundWorker m_bw_receiver;

        /// <summary>
        /// 连接上的IP
        /// </summary>
        public IPAddress ConnectedIP
        {
           get
            {
                if (this.m_socket != null)
                    return ((IPEndPoint)this.m_socket.RemoteEndPoint).Address;
                else
                    return IPAddress.None;
            }
        }

        /// <summary>
        /// 连接上的端口
        /// </summary>
        public int ConnectedPort
        {
            get
            {

                if (this.m_socket != null)
                    return ((IPEndPoint)this.m_socket.RemoteEndPoint).Port;
                else
                    return -1;
            }
        }

        /// <summary>
        /// 是否连接上
        /// </summary>
        public bool Connected
        {
            get
            {
                if (this.m_socket != null)
                    return this.m_socket.Connected;
                else
                    return false;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="i_socket"></param>
        public TcpSvr(Socket i_socket)
        {
            this.m_socket = i_socket;
            this.m_net_work_stream = new NetworkStream(this.m_socket);
            this.m_bw_receiver = new BackgroundWorker();
            this.m_bw_receiver.DoWork += new DoWorkEventHandler(StartReceive);
            this.m_bw_receiver.RunWorkerAsync();
        }

        /// <summary>
        /// 接受数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartReceive(object sender, DoWorkEventArgs e)
        {
            while (this.m_socket.Connected)
            {
                //命令类型
                byte[] t_buffer = new byte[4];
                int t_read_bytes = this.m_net_work_stream.Read(t_buffer, 0, 4);
                if (t_read_bytes == 0)
                    break;
                CommandType t_cmd_type = (CommandType)(BitConverter.ToInt32(t_buffer, 0));

                //接受标识数据总大小
                t_buffer = new byte[4];
                t_read_bytes = this.m_net_work_stream.Read(t_buffer, 0, 4);
                if (t_read_bytes == 0)
                    break;

                int t_sign_data_size = BitConverter.ToInt32(t_buffer, 0);

                //接受标识数据
                t_buffer = new byte[t_sign_data_size];
                t_read_bytes = this.m_net_work_stream.Read(t_buffer, 0, t_sign_data_size);
                if (t_read_bytes == 0)
                    break;

                string t_data_sign = Encoding.UTF8.GetString(t_buffer);

                //接受数据总大小
                t_buffer = new byte[4];
                t_read_bytes = this.m_net_work_stream.Read(t_buffer, 0, 4);
                if (t_read_bytes == 0)
                    break;

                int t_send_data_size = BitConverter.ToInt32(t_buffer, 0);

                //接受数据
                t_buffer = new byte[t_send_data_size];
                t_read_bytes = this.m_net_work_stream.Read(t_buffer, 0, t_send_data_size);
                if (t_read_bytes == 0)
                    break;

                CommandInfo t_cmd_info = new CommandInfo(t_cmd_type, this.ConnectedIP, t_buffer);
                t_cmd_info.DataSign = t_data_sign;

                //接受处理这个消息
                // this.OnCommandReceived(new CommandEventArgs(t_cmd_info));

                t_cmd_info = ProcessComand(t_cmd_info);

                SendCommand2Sender(t_cmd_info);
            }
            //关闭这个连接上通讯
            this.OnDisconnected(new SocketEventArgs(this.m_socket));
            //关闭连接
            this.Disconnect();
        }

        private CommandInfo ProcessComand(CommandInfo i_cmd)
        {
            CommandInfo t_cmd = new CommandInfo();
            if (i_cmd.CommandType == CommandType.ExcuteSQL)
            {
                try
                {
                    int t_ret = DbHelperOra.ExecuteSql(i_cmd.ToString());
                    t_cmd.SenderIP = i_cmd.SenderIP;
                    t_cmd.DataSign = i_cmd.DataSign;
                    t_cmd.CommandType = i_cmd.CommandType;
                    t_cmd.SetSendData(t_ret);
                }
                catch (Exception ex)
                {
                    t_cmd.SenderIP = i_cmd.SenderIP;
                    t_cmd.DataSign = i_cmd.DataSign;
                    t_cmd.CommandType = i_cmd.CommandType;
                    t_cmd.ExData = ex.Message;
                    t_cmd.SetSendData(-1);
                }
            }
            else if (i_cmd.CommandType == CommandType.QueryData)
            {
                try
                {
                    DataSet t_ds = DbHelperOra.Query(i_cmd.ToString());
                    t_cmd.SenderIP = i_cmd.SenderIP;
                    t_cmd.DataSign = i_cmd.DataSign;
                    t_cmd.CommandType = i_cmd.CommandType;
                    t_cmd.SetSendData(t_ds);
                }
                catch (Exception ex)
                {
                    t_cmd.SenderIP = i_cmd.SenderIP;
                    t_cmd.DataSign = i_cmd.DataSign;
                    t_cmd.CommandType = i_cmd.CommandType;
                    t_cmd.ExData = ex.Message;
                }
            }

            return t_cmd;
        }
        

        /// <summary>
        /// 回送消息
        /// </summary>
        /// <param name="i_command"></param>
        public void SendCommand(CommandInfo i_command)
        {
            if (this.m_socket != null && this.m_socket.Connected)
            {
                BackgroundWorker bwSender = new BackgroundWorker();
                bwSender.DoWork += new DoWorkEventHandler(BWSender_DoWork);
                bwSender.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwSender_RunWorkerCompleted);
                bwSender.RunWorkerAsync(i_command);
            }
           
        }

        private void bwSender_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           
            ((BackgroundWorker)sender).Dispose();
             GC.Collect();
        }


        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BWSender_DoWork(object sender, DoWorkEventArgs e)
        {
            CommandInfo t_cmd = (CommandInfo)e.Argument;
            e.Result = this.SendCommand2Sender(t_cmd);
        }


       
        System.Threading.Semaphore t_sph = new System.Threading.Semaphore(1, 1);
        /// <summary>
        /// 消息命令返回给发送者
        /// </summary>
        /// <param name="i_cmd_info"></param>
        /// <returns></returns>
        private bool SendCommand2Sender(CommandInfo i_cmd_info)
        {

            try
            {
                t_sph.WaitOne();
                //命令类型
                byte[] t_buffer = new byte[4];
                t_buffer = BitConverter.GetBytes((int)i_cmd_info.CommandType);

                this.m_net_work_stream.Write(t_buffer, 0, 4);
                this.m_net_work_stream.Flush();

                byte[] t_sign_buffer = Encoding.UTF8.GetBytes(i_cmd_info.DataSign);
                //发送标识数据大小
                t_buffer = new byte[4];
                t_buffer = BitConverter.GetBytes(t_sign_buffer.Length);
                this.m_net_work_stream.Write(t_buffer, 0, 4);
                this.m_net_work_stream.Flush();

                //发送标识数据
                this.m_net_work_stream.Write(t_sign_buffer, 0, t_sign_buffer.Length);
                this.m_net_work_stream.Flush();

                byte[] t_ex_buffer = Encoding.UTF8.GetBytes(i_cmd_info.ExData);
                //发送异常数据大小
                t_buffer = new byte[4];
                t_buffer = BitConverter.GetBytes(t_ex_buffer.Length);
                this.m_net_work_stream.Write(t_buffer, 0, 4);
                this.m_net_work_stream.Flush();

                //发送异常数据
                this.m_net_work_stream.Write(t_ex_buffer, 0, t_ex_buffer.Length);
                this.m_net_work_stream.Flush();

                if (i_cmd_info.SendData == null || i_cmd_info.SendData.Length == 0)
                {
                    i_cmd_info.SetSendData(i_cmd_info.ExData);
                }

                //发送数据大小
                t_buffer = new byte[4];
                t_buffer = BitConverter.GetBytes(i_cmd_info.SendData.Length);

                this.m_net_work_stream.Write(t_buffer, 0, 4);
                this.m_net_work_stream.Flush();

                //发送数据
                this.m_net_work_stream.Write(i_cmd_info.SendData, 0, i_cmd_info.SendData.Length);
                this.m_net_work_stream.Flush();

                t_sph.Release();
                return true;
            }
            catch
            {
                t_sph.Release();
                return false;
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <returns></returns>
        public bool Disconnect()
        {
            if (this.m_socket != null && this.m_socket.Connected)
            {
                try
                {
                    this.m_socket.Shutdown(SocketShutdown.Both);
                    this.m_socket.Close();
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            else
                return true;
        }

        /// <summary>
        /// 接受到命令消息是触发事件
        /// </summary>
        public event CommandReceivedEventHandler CommandReceived;
        /// <summary>
        /// 把事件消息触发
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnCommandReceived(CommandEventArgs e)
        {
            if (CommandReceived != null)
                CommandReceived(this, e);
        }


        /// <summary>
        /// 关闭一个连接时触发事件
        /// </summary>
        public event ServerDisconnectedEventHandler Disconnected;
        /// <summary>
        /// 把关闭事件触发
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnDisconnected(SocketEventArgs e)
        {
            if (Disconnected != null)
                Disconnected(this, e);
        }
	
    }
}
